#pragma once
#include<iostream>
#include<string>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstdlib>
#include<cstring>
using namespace std;

class Sock
{
    public:
    static int Socket()
    {
        int sock = socket(AF_INET, SOCK_STREAM,0);
        if(sock < 0)
        {
            cerr << "socket error: " << strerror(errno) << endl;
            exit(1);
        }
    }
    static void Bind(int sock,uint16_t port)
    {
        struct sockaddr_in addr;
        memset(&addr,0,sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = INADDR_ANY;

        if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
        {
            cerr << "bind() failed: " << strerror(errno)<<endl;
            exit(2);
        }
    }
    static void Listen(int sock)
    {
        if(listen(sock, 5)<0)
        {
            cerr << "Listen() failed: " << strerror(errno) << endl;
            exit(3);
        }
    }
    static int Accept(int sock)
    {
        struct sockaddr_in peer_addr;
        memset(&peer_addr, 0, sizeof(peer_addr));
        socklen_t peer_len = sizeof(peer_addr);
        int new_sock = accept(sock,(struct sockaddr *)&peer_addr,&peer_len);
        if(new_sock > 0)
            return new_sock;
        return -1;
    }
    
    static void Connect(int sock,string ip,uint16_t port)
    {
        struct sockaddr_in server_addr;
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = inet_addr(ip.c_str());
        server_addr.sin_port = htons(port);

        if(connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) <0)
        {
            cout<<"connect failed"<<endl;
            exit(4);
        }
        cout<<"connect succeeded..."<<endl;

    }

};